using System.Collections.Specialized;
using ChessKit.Common.Primitives;

namespace ChessKit.ChessLogics.Internals
{
  internal struct BoardInfo
  {
    private BitVector32 _data;

    private static readonly BitVector32.Section SideOnMoveSection = BitVector32.CreateSection(1);
    private static readonly BitVector32.Section GameStateSection = BitVector32.CreateSection(6, SideOnMoveSection);
    private static readonly BitVector32.Section IsEnPassantSection = BitVector32.CreateSection(1, GameStateSection);
    private static readonly BitVector32.Section EnPassantSection = BitVector32.CreateSection(7, IsEnPassantSection);
    private static readonly BitVector32.Section CastlingStateSection = BitVector32.CreateSection(15, EnPassantSection);
    private static readonly BitVector32.Section HalfmoveClockSection = BitVector32.CreateSection(500, CastlingStateSection);
    private static readonly BitVector32.Section FullmoveNumberSection = BitVector32.CreateSection(500, HalfmoveClockSection);

    /// <summary>The side which is moving next (white or black)</summary>
    public PieceColor SideOnMove
    {
      get { return (PieceColor)_data[SideOnMoveSection]; }
      set { _data[SideOnMoveSection] = (int)value; }
    }
    /// <summary>If set denotes states like check, mate, and draw </summary>
    public GameState GameState
    {
      get { return (GameState)_data[GameStateSection]; }
      set { _data[GameStateSection] = (int)value; }
    }
    /// <summary>Indicates whether the <see cref="EnPassant"/> property value is relevant</summary>
    public bool IsEnPassant
    {
      get { return _data[IsEnPassantSection] != 0; }
      set { _data[IsEnPassantSection] = value ? 1 : 0; }
    }
    /// <summary>Gets the file at which en passant move is available</summary>
    public int EnPassant
    {
      get { return _data[EnPassantSection]; }
      set { _data[EnPassantSection] = value; }
    }
    /// <summary>Gets sides players can castle to</summary>
    public CastlingAvailability Castling
    {
      get { return (CastlingAvailability)_data[CastlingStateSection]; }
      set { _data[CastlingStateSection] = (int)value; }
    }
    /// <summary>Keeps half move number</summary>
    public int HalfmoveClock
    {
      get { return _data[HalfmoveClockSection]; }
      set { _data[HalfmoveClockSection] = value; }
    }
    /// <summary>Keeps full move number</summary>
    public int FullmoveNumber
    {
      get { return _data[FullmoveNumberSection]; }
      set { _data[FullmoveNumberSection] = value; }
    }
  }
}